
bandwidth.rq <- function(p, n, hs = TRUE, alpha = 0.05)
{
	# Bandwidth selection for sparsity estimation two flavors:
	#	Hall and Sheather(1988, JRSS(B)) rate = O(n^{-1/3})
	#	Bofinger (1975, Aus. J. Stat)  -- rate = O(n^{-1/5})
	# Generally speaking, default method, hs=TRUE is preferred.

	x0 <- qnorm(p)
	f0 <- dnorm(x0)
	if(hs)
            n^(-1/3) * qnorm(1 - alpha/2)^(2/3) *
                ((1.5 * f0^2)/(2 * x0^2 + 1))^(1/3)
	else n^-0.2 * ((4.5 * f0^4)/(2 * x0^2 + 1)^2)^ 0.2
}


plot.rq.process <- function(x, nrow = 3, ncol = 2, ...)
{
    ## Function to plot estimated quantile regression  process
	tdim <- dim(x$sol)
	p <- tdim[1] - 3
	m <- tdim[2]
	oldpar <- par(no.readonly=TRUE)
	par(mfrow = c(nrow, ncol))
	ylab <- dimnames(x$sol)[[1]]
	for(i in 1:p) {
		plot(x$sol[1,], x$sol[3 + i,  ], xlab = "tau",
                     ylab = ylab[3 + i], type = "l")
	}
par(oldpar)
}

print.rqs <- function (x, ...)
{
    if (!is.null(cl <- x$call)) {
        cat("Call:\n")
        dput(cl)
    }
    coef <- coef(x)
    cat("\nCoefficients:\n")
    print(coef, ...)
    rank <- x$rank
    nobs <- nrow(residuals(x))
    p <- nrow(coef)
    rdf <- nobs - p
    cat("\nDegrees of freedom:", nobs, "total;", rdf, "residual\n")
    if (!is.null(attr(x, "na.message")))
        cat(attr(x, "na.message"), "\n")
    invisible(x)
}

"print.rq" <-
function(x, ...)
{
	if(!is.null(cl <- x$call)) {
		cat("Call:\n")
		dput(cl)
	}
	coef <- coef(x)
	cat("\nCoefficients:\n")
	print(coef, ...)
	rank <- x$rank
	nobs <- length(residuals(x))
	if(is.matrix(coef))
		p <- dim(coef)[1]
	else p <- length(coef)
	rdf <- nobs - p
	cat("\nDegrees of freedom:", nobs, "total;", rdf, "residual\n")
	if(!is.null(attr(x, "na.message")))
		cat(attr(x, "na.message"), "\n")
	invisible(x)
}

print.summary.rqs <- function(x, ...) {
    lapply(x, print.summary.rq)
    invisible(x)
}

"print.summary.rq" <-
function(x, digits = max(5, .Options$digits - 2), ...)
{
	cat("\nCall: ")
	dput(x$call)
	coef <- x$coef
	## df <- x$df
	## rdf <- x$rdf
	tau <- x$tau
	cat("\ntau: ")
	print(format(round(tau,digits = digits)), quote = FALSE, ...)
	cat("\nCoefficients:\n")
	print(format(round(coef, digits = digits)), quote = FALSE, ...)
	invisible(x)
}

"rq" <-
function (formula, tau = 0.5, data, subset, weights, na.action, method = "br",
    model = TRUE, contrasts = NULL, ...)
{
    call <- match.call()
    mf <- match.call(expand.dots = FALSE)
    m <- match(c("formula", "data", "subset", "weights", "na.action"), names(mf), 0)
    mf <- mf[c(1,m)]
    mf$drop.unused.levels <- TRUE
    mf[[1]] <- as.name("model.frame")
    mf <- eval.parent(mf)
    if(method == "model.frame")return(mf)
    mt <- attr(mf, "terms")
    weights <- as.vector(model.weights(mf))
    Y <- model.response(mf)
    if(method == "sfn"){
	if(requireNamespace("MatrixModels") && requireNamespace("Matrix")){
	    X <- MatrixModels::model.Matrix(mt, data, sparse = TRUE)
	    vnames <- dimnames(X)[[2]]
	    X <- as(X ,"matrix.csr")
	    mf$x <- X
	    }
    }	
    else
	X <- model.matrix(mt, mf, contrasts)
    eps <- .Machine$double.eps^(2/3)
    Rho <- function(u,tau) u * (tau - (u < 0))
    if(length(tau)>1){
	if(any(tau < 0) || any(tau > 1))
		stop("invalid tau:  taus should be >= 0 and <= 1")
	if(any(tau == 0)) tau[tau == 0] <- eps
	if(any(tau == 1)) tau[tau == 1] <- 1 -eps
	coef <- matrix(0,ncol(X),length(tau))
        rho <- rep(0,length(tau))
	fitted <- resid <- matrix(0,nrow(X),length(tau))
	for(i in 1:length(tau)){
	    z <- {if (length(weights))
                 	rq.wfit(X, Y, tau = tau[i], weights, method, ...)
                  else rq.fit(X, Y, tau = tau[i], method, ...)
    		 }
	    coef[,i] <- z$coefficients
	    resid[,i] <- z$residuals
            rho[i] <- sum(Rho(z$residuals,tau[i]))
	    fitted[,i] <- Y - z$residuals
	   }
	taulabs <- paste("tau=",format(round(tau,3)))
	dimnames(coef) <- list(dimnames(X)[[2]],taulabs)
	dimnames(resid) <- list(dimnames(X)[[1]],taulabs)
	fit <- z
        fit$coefficients <-  coef
        fit$residuals <- resid
        fit$fitted.values <- fitted
	if(method == "lasso") class(fit) <- c("lassorqs","rqs")
	else if(method == "scad") class(fit) <- c("scadrqs","rqs")
	else class(fit) <- "rqs"
	}
    else{
        process <- (tau < 0 || tau > 1)
	if(tau == 0) tau <- eps
	if(tau == 1) tau <- 1 -eps
        fit <- {
            if (length(weights))
                rq.wfit(X, Y, tau = tau, weights, method, ...)
            else rq.fit(X, Y, tau = tau, method, ...)
           }
	if(process)
		rho <- list(x = fit$sol[1,],y = fit$sol[3,])
	else {
		if(length(dim(fit$residuals)))
		    dimnames(fit$residuals) <- list(dimnames(X)[[1]],NULL)
                rho <-  sum(Rho(fit$residuals,tau))
		}
	if(method == "lasso") class(fit) <- c("lassorq","rq")
	else if(method == "scad") class(fit) <- c("scadrq","rq")
        else class(fit) <- ifelse(process, "rq.process", "rq")
	}
    fit$na.action <- attr(mf, "na.action")
    fit$formula <- formula
    fit$terms <- mt
    fit$xlevels <- .getXlevels(mt,mf)
    fit$call <- call
    fit$tau <- tau
    fit$weights <- weights
    fit$residuals <- drop(fit$residuals)
    fit$rho <- rho
    fit$method <- method
    fit$fitted.values <- drop(fit$fitted.values)

    attr(fit, "na.message") <- attr(m, "na.message")
    if(model) fit$model <- mf
    fit
}
"rq.fit" <-
function(x, y, tau = 0.5, method = "br", ...)
{
    if(length(tau) > 1) {
	    tau <- tau[1]
	    warning("Multiple taus not allowed in rq.fit: solution restricted to first element")
	}

    fit <- switch(method,
		fn = rq.fit.fnb(x, y, tau = tau, ...),
		fnb = rq.fit.fnb(x, y, tau = tau, ...),
		fnc = rq.fit.fnc(x, y, tau = tau, ...),
		sfn = rq.fit.sfn(x, y, tau = tau, ...),
		pfn = rq.fit.pfn(x, y, tau = tau, ...),
		br = rq.fit.br(x, y, tau = tau, ...),
		lasso = rq.fit.lasso(x, y, tau = tau, ...),
		scad = rq.fit.scad(x, y, tau = tau, ...),
		{
			what <- paste("rq.fit.", method, sep = "")
			if(exists(what, mode = "function"))
				(get(what, mode = "function"))(x, y, ...)
			else stop(paste("unimplemented method:", method))
		}
		)
	fit$fitted.values <- y - fit$residuals
	fit$contrasts <- attr(x, "contrasts")
	fit
}
"rqs.fit"<-
function(x, y, tau = 0.5, tol = 0.0001)
{
# function to compute rq fits for multiple y's
        x <- as.matrix(x)
        p <- ncol(x)
        n <- nrow(x)
        m <- ncol(y)
        z <- .Fortran("rqs",
                as.integer(n),
                as.integer(p),
                as.integer(m),
                as.integer(n + 5),
                as.integer(p + 2),
                as.double(x),
                as.double(y),
                as.double(tau),
                as.double(tol),
                flag = integer(m),
                coef = double(p * m),
                resid = double(n),
                integer(n),
                double((n + 5) * (p + 2)),
                double(n))
        if(sum(z$flag)>0){
                if(any(z$flag)==2)
                        warning(paste(sum(z$flag==2),"out of",m,
                                "BS replications have near singular design"))
                if(any(z$flag)==1)
                        warning(paste(sum(z$flag==1),"out of",m,"may be nonunique"))
                }
        return(t(matrix(z$coef, p, m)))
}
"formula.rq" <-
function (x, ...)
{
    form <- x$formula
    if (!is.null(form)) {
        form <- formula(x$terms)
        environment(form) <- environment(x$formula)
        form
    }
    else formula(x$terms)
}

"predict.rq" <-
function (object, newdata, type = "none", interval = c("none",
    "confidence"), level = 0.95, na.action = na.pass, ...)
{
    if (missing(newdata))
        return(object$fitted)
    else {
        tt <- terms(object)
        Terms <- delete.response(tt)
        m <- model.frame(Terms, newdata, na.action = na.action,
            xlev = object$xlevels)
        if (!is.null(cl <- attr(Terms, "dataClasses")))
            .checkMFClasses(cl, m)
        X <- model.matrix(Terms, m, contrasts.arg = object$contrasts)
    }
    pred <- drop(X %*% object$coefficients)
    dots <- list(...)
    if (length(dots$se))
        boot <- (dots$se == "boot")
    else boot <- FALSE
    if (length(dots$mofn))
         mofn <- dots$mofn
    interval <- match.arg(interval)
    if (!interval == "none") {
        if (interval == "confidence") {
            if (type == "percentile") {
                if (boot) {
		    if(exists("mofn")) {# Rescale and recenter!!
		      n <- length(object$fitted)
                      factor <- ifelse(mofn < n, sqrt(mofn/n), 1)
                      XB <- X %*% t(summary(object, cov = TRUE, ...)$B)/factor
                      pl <- apply(XB, 1, function(x) quantile(x, (1 - level)/2))
                      pu <- apply(XB, 1, function(x) quantile(x, 1 - (1 - level)/2))
                      pl <- pred + factor * (pl - pred)
                      pu <- pred + factor * (pu - pred)
                  }
                  else {
                      XB <- X %*% t(summary(object, cov = TRUE, ...)$B)
                      pl <- apply(XB, 1, function(x) quantile(x, (1 - level)/2))
                      pu <- apply(XB, 1, function(x) quantile(x, 1 - (1 - level)/2))
                  }
                  pred <- cbind(pred, pl, pu)
                  colnames(pred) <- c("fit", "lower", "higher")
                }
                else stop("Percentile method requires se = \"boot\".")
            }
            else if (type == "direct") {
                if (boot)
                  stop("Direct method incompatible with bootstrap covariance matrix estimation")
                Z <- rq.fit(object$x, object$y, tau = -1)$sol
                V <- summary(object, cov = TRUE, ...)
                df <- V$rdf
                tfrac <- qt(1 - (1 - level)/2, df)
                Vun <- V$cov * V$scale^2
                tau <- object$tau
                bn <- tfrac * sqrt(diag(X %*% Vun %*% t(X)))
                tauU <- pmin(tau + bn, 1 - 1/df)
                tauL <- pmax(tau - bn, 1/df)
                tauhat <- Z[1, ]
                yhat <- X %*% Z[-(1:3), ]
                n <- nrow(X)
                pl <- yhat[cbind(1:n, cut(tauL, tauhat, label = FALSE))]
                pu <- yhat[cbind(1:n, cut(tauU, tauhat, label = FALSE))]
                pred <- cbind(pred, pl, pu)
                colnames(pred) <- c("fit", "lower", "higher")
            }
            else {
                V <- summary(object, cov = TRUE, ...)
                df <- V$rdf
                tfrac <- qt((1 - level)/2, df)
                sdpred <- sqrt(diag(X %*% V$cov %*% t(X)))
                pred <- cbind(pred, pred + tfrac * sdpred %o%
                  c(1, -1))
                colnames(pred) <- c("fit", "lower", "higher")
            }
        }
        else stop(paste("No interval method for", interval))
    }
    pred
}

"predict.rqs" <-
function (object, newdata, type = "Qhat", stepfun = FALSE, na.action = na.pass, ...)
{
   ## with all defaults
   if(missing(newdata) && !stepfun && (type == "Qhat")) return(object$fitted)

   ## otherwise
   tt <- delete.response(terms(object))
   m <- if(missing(newdata)) model.frame(object) else model.frame(tt, newdata,
       na.action = na.action, xlev = object$xlevels)
   if(!is.null(cl <- attr(tt, "dataClasses"))) .checkMFClasses(cl, m)
   X <- model.matrix(tt, m, contrasts = object$contrasts)
   pred <- t(X %*% object$coefficients)
   taus <- object$tau
   M <- NCOL(pred)

   ## return stepfun or matrix
   if(stepfun) {
       if(type == "Qhat"){
	   pred <- rbind(pred[1,],pred)
          if(M > 1) 
	      f <- apply(pred, 2, function(y) stepfun(taus, y))
          else
              f <- stepfun(taus, c(pred[1,1], pred[,1]))
          }
       else if(type == "Fhat"){
	   taus <- c(taus[1], taus)
           if(M > 1) 
	       f <- apply(pred, 2, function(y) {
                        o <- order(y)
                        stepfun(y[o], taus[c(1,o)])})
          else
              f <- stepfun(pred[,1],taus)
       }
       else stop("Stepfuns must be either 'Qhat' or 'Fhat'\n")
       return(f)
   } 
   else if(type == "fhat"){
	akjfun <- function(z, p, d = 10, g = 300, ...) {
            mz <- sum(z * p)
            sz <- sqrt(sum((z - mz)^2 * p))
            hz <- seq(mz - d * sz, mz + d * sz, length = g)
            fz <- akj(z, hz, p = p, ...)$dens
            approxfun(hz, fz)
        }
        p <- diff(taus)
        if (M > 1) 
            f <- apply(pred[-1, ], 2, function(z) akjfun(z, p, ...))
        else akjfun(pred[, 1], p, ...)
        return(f)
    }
  else return(t(pred))
}


"predict.rq.process" <-
function (object, newdata, type = "Qhat", stepfun = FALSE, na.action = na.pass, ...)
{
    if(missing(newdata) && !stepfun && (type == "Qhat")) return(object$fitted)
    tt <- terms(object)
    Terms <- delete.response(tt)
    m <- model.frame(Terms, newdata, na.action = na.action,
        xlev = object$xlevels)
    if (!is.null(cl <- attr(Terms, "dataClasses"))) .checkMFClasses(cl, m)
    X <- model.matrix(Terms, m, contrasts = object$contrasts)
    if(!length(X)) X <- rep(1, NROW(object$dsol)) # intercept only hack
    pred <- t(X %*% object$sol[-(1:3),, drop = FALSE])
    taus <- object$sol[1,]
    M <- NCOL(pred)
    if(stepfun){
       if(type == "Qhat"){
	  pred <- rbind(pred[1,], pred)
          if(M > 1)
	      f <- apply(pred,2,function(y) stepfun(taus, y))
          else
              f <- stepfun(taus, pred[,1])
          }
       else if(type == "Fhat"){
	  taus <- c(taus[1],taus)
          if(M > 1) 
	      f <- apply(pred,2,function(y) stepfun(y,t))
          else
              f <- stepfun(pred[,1],c(taus[1],taus))
          }
       else stop("Stepfuns must be either 'Qhat' or 'Fhat'")
       return(f)
    }
    else if(type == "fhat"){
	akjfun <- function(z, p, d = 10, g = 300, ...){
	   mz <- sum(z * p)
	   sz <- sqrt(sum((z - mz)^2 * p))
           hz <- seq(mz -  d * sz, mz+ d * sz, length = g)
           fz <- akj(z, hz, p = p, ...)$dens
           approxfun(hz,fz)
	}
	p <- diff(taus)
        if(M > 1) 
	    f <- apply(pred[-1,], 2, function(z) akjfun(z, p, ...))
        else
	   akjfun(pred[,1], p, ...)
       return(f)
       }
    else return(t(pred))
}
"rearrange"  <- function (f, xmin, xmax)
# Revised Version September 11 2007.
{
    if (is.list(f))
        lapply(f, rearrange)
    else {
        if (!is.stepfun(f))
            stop("Only stepfuns can be rearranged.\n")
    	call	<- attributes(f)$call;
    	right <- call[match("right",names(call))]=="TRUE()"
        x 	<- knots(f)
	n	<- length(x)
	if(missing(xmin)) xmin = x[1]
	if(missing(xmax)) xmax = x[n]
	x	<- x[(x >= xmin) & (x <= xmax)]
	x	<- c(xmin, x, xmax)
	n	<- length(x)
	y	<- f(x)
        o 	<- ifelse(rep(right,n-1), order(y[-1])+1, order(y[-n]))
        x 	<- cumsum(c(x[1], diff(x)[o - right]))
        y 	<- y[o]
        y 	<- c(y[1], y, max(y))
        stepfun(x, y, right = right)
    }

}



# Function to compute regression quantiles using original simplex approach
# of Barrodale-Roberts/Koenker-d'Orey.  There are several options.
# The options are somewhat different than those available for the Frisch-
# Newton version of the algorithm, reflecting the different natures of the
# problems typically solved.  Succintly BR for "small" problems, FN for
# "large" ones.  Obviously, these terms are conditioned by available hardware.
#
# Basically there are two modes of use:
# 1.  For Single Quantiles:
#
#       if tau is between 0 and 1 then only one quantile solution is computed.
#
#       if ci = FALSE  then just the point estimate and residuals are returned
#		If the column dimension of x is 1 then ci is set to FALSE since
#		since the rank inversion method has no proper null model.
#       if ci = TRUE  then there are two options for confidence intervals:
#
#               1.  if iid = TRUE we get the original version of the rank
#                       inversion intervals as in Koenker (1994)
#               2.  if iid = FALSE we get the new version of the rank inversion
#                       intervals which accounts for heterogeneity across
#                       observations in the conditional density of the response.
#                       The theory of this is described in Koenker-Machado(1999)
#               Both approaches involve solving a parametric linear programming
#               problem, the difference is only in the factor qn which
#               determines how far the PP goes.  In either case one can
#               specify two other options:
#                       1. interp = FALSE returns two intervals an upper and a
#                               lower corresponding to a level slightly
#                               above and slightly below the one specified
#                               by the parameter alpha and dictated by the
#                               essential discreteness in the test statistic.
#				interp = TRUE  returns a single interval based on
#                               linear interpolation of the two intervals
#                               returned:  c.values and p.values which give
#                               the critical values and p.values of the
#                               upper and lower intervals. Default: interp = TRUE.
#                       2.  tcrit = TRUE uses Student t critical values while
#                               tcrit = FALSE uses normal theory ones.
# 2. For Multiple Quantiles:
#
#       if tau < 0 or tau >1 then it is presumed that the user wants to find
#       all of the rq solutions in tau, and the program computes the whole
#	quantile regression solution as a process in tau, the resulting arrays
#	containing the primal and dual solutions, betahat(tau), ahat(tau)
#       are called sol and dsol.  These arrays aren't printed by the default
#       print function but they are available as attributes.
#       It should be emphasized that this form of the solution can be
#	both memory and cpu quite intensive.  On typical machines it is
#	not recommended for problems with n > 10,000.
#	In large problems a grid of solutions is probably sufficient.
#
rq.fit.br <-
function (x, y, tau = 0.5, alpha = 0.1, ci = FALSE, iid = TRUE,
	interp = TRUE, tcrit = TRUE)
{
    tol <- .Machine$double.eps^(2/3)
    eps <- tol
    big <- .Machine$double.xmax
    x <- as.matrix(x)
    p <- ncol(x)
    n <- nrow(x)
    ny <- NCOL(y)
    nsol <- 2
    ndsol <- 2
    # Check for Singularity of X since br fortran isn't very reliable about this
    if (qr(x)$rank < p)
        stop("Singular design matrix")
    if (tau < 0 || tau > 1) {
        nsol <- 3 * n
        ndsol <- 3 * n
        lci1 <- FALSE
        qn <- rep(0, p)
        cutoff <- 0
        tau <- -1
    }
    else {
        if (p == 1)
            ci <- FALSE
        if (ci) {
            lci1 <- TRUE
            if (tcrit)
                cutoff <- qt(1 - alpha/2, n - p)
            else cutoff <- qnorm(1 - alpha/2)
            if (!iid) {
                h <- bandwidth.rq(tau, n, hs = TRUE)
                bhi <- rq.fit.br(x, y, tau + h, ci = FALSE)
                bhi <- coefficients(bhi)
                blo <- rq.fit.br(x, y, tau - h, ci = FALSE)
                blo <- coefficients(blo)
                dyhat <- x %*% (bhi - blo)
                if (any(dyhat <= 0)) {
                  pfis <- (100 * sum(dyhat <= 0))/n
                  warning(paste(pfis, "percent fis <=0"))
                }
                f <- pmax(eps, (2 * h)/(dyhat - eps))
                qn <- rep(0, p)
                for (j in 1:p) {
                  qnj <- lm(x[, j] ~ x[, -j] - 1, weights = f)$resid
                  qn[j] <- sum(qnj * qnj)
                }
            }
            else qn <- 1/diag(solve(crossprod(x)))
        }
        else {
            lci1 <- FALSE
            qn <- rep(0, p)
            cutoff <- 0
        }
    }
    z <- .Fortran("rqbr", as.integer(n), as.integer(p), as.integer(n +
        5), as.integer(p + 3), as.integer(p + 4), as.double(x),
        as.double(y), as.double(tau), as.double(tol), flag = as.integer(1),
        coef = double(p), resid = double(n), integer(n), double((n +
            5) * (p + 4)), double(n), as.integer(nsol), as.integer(ndsol),
        sol = double((p + 3) * nsol), dsol = double(n * ndsol),
        lsol = as.integer(0), h = integer(p * nsol), qn = as.double(qn),
        cutoff = as.double(cutoff), ci = double(4 * p), tnmat = double(4 *
            p), as.double(big), as.logical(lci1))
    if (z$flag != 0)
        warning(switch(z$flag, "Solution may be nonunique", "Premature end - possible conditioning problem in x"))
    if (tau < 0 || tau > 1) {
        sol <- matrix(z$sol[1:((p + 3) * z$lsol)], p + 3)
        dsol <- matrix(z$dsol[1:(n * z$lsol)], n)
        vnames <- dimnames(x)[[2]]
        dimnames(sol) <- list(c("tau", "Qbar", "Obj.Fun", vnames),
            NULL)
        return(list(sol = sol, dsol = dsol))
    }
    if (!ci) {
        coef <- z$coef
        dual <- z$dsol[1:n]
        names(coef) <- dimnames(x)[[2]]
        return(list(coefficients = coef, x = x, y = y, residuals = y - x %*% z$coef,
		dual = dual))
    }
    if (interp) {
        Tn <- matrix(z$tnmat, nrow = 4)
        Tci <- matrix(z$ci, nrow = 4)
        Tci[3, ] <- Tci[3, ] + (abs(Tci[4, ] - Tci[3, ]) * (cutoff -
            abs(Tn[3, ])))/abs(Tn[4, ] - Tn[3, ])
        Tci[2, ] <- Tci[2, ] - (abs(Tci[1, ] - Tci[2, ]) * (cutoff -
            abs(Tn[2, ])))/abs(Tn[1, ] - Tn[2, ])
        Tci[2, ][is.na(Tci[2, ])] <- -big
        Tci[3, ][is.na(Tci[3, ])] <- big
        coefficients <- cbind(z$coef, t(Tci[2:3, ]))
        vnames <- dimnames(x)[[2]]
        cnames <- c("coefficients", "lower bd", "upper bd")
        dimnames(coefficients) <- list(vnames, cnames)
        residuals <- y - drop(x %*% z$coef)
        return(list(coefficients = coefficients, residuals = residuals))
    }
    else {
        Tci <- matrix(z$ci, nrow = 4)
        coefficients <- cbind(z$coef, t(Tci))
        residuals <- y - drop(x %*% z$coef)
        vnames <- dimnames(x)[[2]]
        cnames <- c("coefficients", "lower bound", "Lower Bound",
            "upper bd", "Upper Bound")
        dimnames(coefficients) <- list(vnames, cnames)
        c.values <- t(matrix(z$tnmat, nrow = 4))
        c.values <- c.values[, 4:1]
        dimnames(c.values) <- list(vnames, cnames[-1])
        p.values <- if (tcrit)
            matrix(pt(c.values, n - p), ncol = 4)
        else matrix(pnorm(c.values), ncol = 4)
        dimnames(p.values) <- list(vnames, cnames[-1])
        list(coefficients = coefficients, residuals = residuals,
            c.values = c.values, p.values = p.values)
    }
}

"rq.fit.fnb" <-
function (x, y, tau = 0.5, rhs = (1-tau)*apply(x,2,sum), beta = 0.99995, eps = 1e-06)
{
    n <- length(y)
    p <- ncol(x)
    if (n != nrow(x))
        stop("x and y don't match n")
    if (tau < eps || tau > 1 - eps)
        stop("No parametric Frisch-Newton method.  Set tau in (0,1)")
    d   <- rep(1,n)
    u   <- rep(1,n)
    wn <- rep(0,10*n)
    wn[1:n] <- (1-tau) #initial value of dual solution
    z <- .Fortran("rqfnb", as.integer(n), as.integer(p), a = as.double(t(as.matrix(x))),
        c = as.double(-y), rhs = as.double(rhs), d = as.double(d),as.double(u),
        beta = as.double(beta), eps = as.double(eps),
        wn = as.double(wn), wp = double((p + 3) * p),
        it.count = integer(3), info = integer(1))
    if (z$info != 0)
        stop(paste("Error info = ", z$info, "in stepy: singular design"))
    coefficients <- -z$wp[1:p]
    names(coefficients) <- dimnames(x)[[2]]
    residuals <- y - x %*% coefficients
    list(coefficients=coefficients, tau=tau, residuals=residuals)
}

"rq.fit.fnc" <-
function (x, y, R, r, tau = 0.5, beta = 0.9995, eps = 1e-06)
{
    n1 <- length(y)
    n2 <- length(r)
    p <- ncol(x)
    if (n1 != nrow(x))
        stop("x and y don't match n1")
    if (n2 != nrow(R))
        stop("R and r don't match n2")
    if (p != ncol(R))
        stop("R and x don't match p")
    if (tau < eps || tau > 1 - eps)
        stop("No parametric Frisch-Newton method.  Set tau in (0,1)")
    rhs <- (1 - tau) * apply(x, 2, sum)
    u <- rep(1, max(n1,n2)) #upper bound vector and scratch vector
    wn1 <- rep(0, 9 * n1)
    wn1[1:n1] <- (1 - tau) #store the values of x1
    wn2 <- rep(0, 6 * n2)
    wn2[1:n2] <- 1 #store the values of x2
    z <- .Fortran("rqfnc", as.integer(n1), as.integer(n2), as.integer(p),
	a1 = as.double(t(as.matrix(x))), c1 = as.double(-y),
	a2 = as.double(t(as.matrix(R))), c2 = as.double(-r),
	rhs = as.double(rhs), d1 = double(n1), d2 = double(n2),
	as.double(u), beta = as.double(beta), eps = as.double(eps),
        wn1 = as.double(wn1), wn2 = as.double(wn2), wp = double((p + 3) * p),
        it.count = integer(3), info = integer(1))
    if (z$info != 0)
        stop(paste("Error info = ", z$info, "in stepy2: singular design"))
    coefficients <- -z$wp[1:p]
    names(coefficients) <- dimnames(x)[[2]]
    residuals <- y - x %*% coefficients
    it.count <- z$it.count
    list(coefficients=coefficients, tau=tau, residuals=residuals, it = it.count)
}
"rq.fit.scad" <-
function (x, y, tau = 0.5, alpha = 3.2, lambda = 1, start = "rq", beta = 0.9995, eps = 1e-06)
{
    n <- length(y)
    p <- ncol(x)
    if (n != nrow(x))
        stop("x and y don't match n")
    if (tau < eps || tau > 1 - eps)
        stop("No parametric Frisch-Newton method.  Set tau in (0,1)")
    if(length(lambda) == 1)
         lambda <- c(0,rep(lambda,p-1))
    if(length(lambda) != p)
          stop(paste("lambda must be either of length ",p," or length one"))
    if(any(lambda < 0))
          stop("negative lambdas disallowed")
    R <- diag(lambda,nrow = length(lambda))
    R <- R[which(lambda != 0),, drop = FALSE]
    r <- rep(0,nrow(R))
    X <- rbind(x,  R)
    Y <- c(y, r)
    N <- length(Y)
    rhs <- (1 - tau) * apply(x, 2, sum) + apply(R,2,sum)
    dscad <- function(x, a = 3.7, lambda = 2){
        lambda *  sign(x) *  (abs(x) <= lambda) +
        sign(x) * (a * lambda -  abs(x)) / (a - 1) *
                (abs(x) <= a * lambda) * (abs(x) > lambda)
        }
    binit <- switch(start,
    	rq =   rq.fit.fnb(x, y, tau = tau)$coef[-1],
    	lasso = rq.fit.lasso(x, y, tau = tau, lambda = lambda)$coef[-1]
	)
    coef <- rep(.Machine$double.xmax,p)
    vscad <- rhs - c(0,dscad(binit) * sign(binit))
    it <- 0
    while(sum(abs(binit - coef[-1])) > eps){
	it <- it + 1
    	d <- rep(1, N)
    	u <- rep(1, N)
    	wn <- rep(0, 10 * N)
    	wn[1:N] <- c(rep((1 - tau),n),rep(.5,nrow(R)))
	vrhs <- rhs - vscad
	binit <- coef[-1]
    	z <- .Fortran("rqfnb", as.integer(N), as.integer(p), a = as.double(t(as.matrix(X))),
        	c = as.double(-Y), vrhs = as.double(vrhs), d = as.double(d),
        	as.double(u), beta = as.double(beta), eps = as.double(eps),
        	wn = as.double(wn), wp = double((p + 3) * p), 
            	it.count = integer(3), info = integer(1))
	coef <- -z$wp[1:p]
	vscad <- c(0,dscad(coef[2:p]) * sign(coef[2:p]))
	}
    if (z$info != 0)
        stop(paste("Error info = ", z$info, "in stepy2: singular design"))
    coefficients <- -z$wp[1:p]
    names(coefficients) <- dimnames(x)[[2]]
    residuals <- y - x %*% coefficients
    it.count <- z$it.count
    list(coefficients=coefficients, residuals=residuals, tau = tau,
		lambda = lambda, it = it.count)
}


"rq.fit.lasso" <-
function (x, y, tau = 0.5, lambda = 1, beta = 0.9995, eps = 1e-06)
{
    n <- length(y)
    p <- ncol(x)
    if (n != nrow(x))
        stop("x and y don't match n")
    if(length(lambda) == 1)
         lambda <- c(0,rep(lambda,p-1))
    if(length(lambda) != p)
          stop(paste("lambda must be either of length ",p," or length one"))
    if(any(lambda < 0))
          stop("negative lambdas disallowed")
    R <- diag(lambda,nrow = length(lambda))
    R <- R[which(lambda != 0),, drop = FALSE]
    r <- rep(0,nrow(R))
    if (tau < eps || tau > 1 - eps)
        stop("No parametric Frisch-Newton method.  Set tau in (0,1)")
    X <- rbind(x, R)
    Y <- c(y, r)
    N <- length(Y)
    rhs <- (1 - tau) * apply(x, 2, sum) + 0.5 * apply(R,2,sum)
    d <- rep(1, N)
    u <- rep(1, N)
    wn <- rep(0, 10 * N)
    wn[1:N] <- rep(0.5, N)
    z <- .Fortran("rqfnb", as.integer(N), as.integer(p), a = as.double(t(as.matrix(X))),
        c = as.double(-Y), rhs = as.double(rhs), d = as.double(d),
        as.double(u), beta = as.double(beta), eps = as.double(eps),
        wn = as.double(wn), wp = double((p + 3) * p), 
            it.count = integer(3), info = integer(1))
    if (z$info != 0)
        stop(paste("Error info = ", z$info, "in stepy2: singular design"))
    coefficients <- -z$wp[1:p]
    names(coefficients) <- dimnames(x)[[2]]
    residuals <- y - x %*% coefficients
    it.count <- z$it.count
    list(coefficients=coefficients, residuals=residuals, tau = tau,
	lambda = lambda, it = it.count)
}

"rq.fit.pfn" <-
# This is an implementation (purely in R) of the preprocessing phase
# of the rq algorithm described in Portnoy and Koenker, Statistical
# Science, (1997) 279-300.  In this implementation it can be used
# as an alternative method for rq() by specifying method="pfn"
# It should probably be used only on very large problems and then
# only with some caution.  Very large in this context means roughly
# n > 100,000.  The options are described in the paper, and more
# explicitly in the code.  Again, it would be nice perhaps to have
# this recoded in a lower level language, but in fact this doesn't
# seem to make a huge difference in this case since most of the work
# is already done in the rq.fit.fnb calls.
#
function(x, y, tau = 0.5,  Mm.factor = 0.8,
	max.bad.fixup = 3, eps = 1e-6)
{
	#rq function for n large --
	n <- length(y)
	if(nrow(x) != n)
		stop("x and y don't match n")
	if(tau < 0 | tau > 1)
		stop("tau outside (0,1)")
	p <- ncol(x)
	m <- round(((p + 1) * n)^(2/3))
	not.optimal <- TRUE
	while(not.optimal) {
		if(m < n)
			s <- sample(n, m)
		else {
			b <- rq.fit.fnb(x, y, tau = tau,  eps = eps)$coef
			break
		}
		xx <- x[s,  ]
		yy <- y[s]
		z <- rq.fit.fnb(xx, yy, tau = tau,  eps = eps)
		xxinv <- solve(chol(crossprod(xx)))
		band <- sqrt(((x %*% xxinv)^2) %*% rep(1, p))
		#sqrt(h<-ii)
		r <- y - x %*% z$coef
		M <- Mm.factor * m
		lo.q <- max(1/n, tau - M/(2 * n))
		hi.q <- min(tau + M/(2 * n), (n - 1)/n)
		kappa <- quantile(r/pmax(eps, band), c(lo.q, hi.q))
		sl <- r < band * kappa[1]
		su <- r > band * kappa[2]
		bad.fixup <- 0
		while(not.optimal & (bad.fixup < max.bad.fixup)) {
			xx <- x[!su & !sl,  ]
			yy <- y[!su & !sl]
			if(any(sl)) {
				glob.x <- c(t(x[sl,  , drop = FALSE]) %*% rep(
					1, sum(sl)))
				glob.y <- sum(y[sl])
				xx <- rbind(xx, glob.x)
				yy <- c(yy, glob.y)
			}
			if(any(su)) {
				ghib.x <- c(t(x[su,  , drop = FALSE]) %*% rep(
					1, sum(su)))
				ghib.y <- sum(y[su])
				xx <- rbind(xx, ghib.x)
				yy <- c(yy, ghib.y)
			}
			z <- rq.fit.fnb(xx, yy, tau = tau,  eps = eps)
			b <- z$coef
			r <- y - x %*% b
			su.bad <- (r < 0) & su
			sl.bad <- (r > 0) & sl
			if(any(c(su.bad, sl.bad))) {
				if(sum(su.bad | sl.bad) > 0.10000000000000001 *
					M) {
					warning("Too many fixups:  doubling m")
					m <- 2 * m
					break
				}
				su <- su & !su.bad
				sl <- sl & !sl.bad
				bad.fixup <- bad.fixup + 1
			}
			else not.optimal <- FALSE
		}
	}
	coefficients <- b
	names(coefficients) <- dimnames(x)[[2]]
	residuals <- y - x %*% b
	return(list(coefficients=coefficients, tau=tau,
		residuals=residuals))
}

"rq.wfit" <-
function(x, y, tau = 0.5, weights, method = "br",  ...)
{
	if(any(weights < 0))
		stop("negative weights not allowed")
	if(length(tau) > 1) {
	    tau <- tau[1]
	    warning("Multiple taus not allowed in rq.wfit: solution restricted to first element")
	}
	contr <- attr(x, "contrasts")
	wx <- x * weights
	wy <- y * weights
	fit <- switch(method,
		fn = rq.fit.fnb(wx, wy, tau = tau, ...),
		fnb = rq.fit.fnb(wx, wy, tau = tau, ...),
		br = rq.fit.br(wx, wy, tau = tau, ...),
		fnc = rq.fit.fnc(wx, wy, tau = tau, ...),
		sfn = rq.fit.sfn(wx, wy, tau = tau, ...),
                pfn = rq.fit.pfn(wx, wy, tau = tau, ...), {
			what <- paste("rq.fit.", method, sep = "")
			if(exists(what, mode = "function"))
				(get(what, mode = "function"))(x, y, ...)
			else stop(paste("unimplemented method:", method))
		}
		)
        if(length(fit$sol))
            fit$fitted.values <- x %*% fit$sol[-(1:3),]
        else
            fit$fitted.values <- x %*% fit$coef
	fit$residuals <- y - fit$fitted.values
	fit$contrasts <- attr(x, "contrasts")
	fit$weights <- weights
	fit
}

"summary.rqs" <-
function (object, ...) {
        taus <- object$tau
        xsum <- as.list(taus)
	dots <- list(...)
	U <- NULL # Reuse bootstrap randomization
        for(i in 1:length(taus)){
                xi <- object
                xi$coefficients <- xi$coefficients[,i]
                xi$residuals <- xi$residuals[,i]
                xi$tau <- xi$tau[i]
                class(xi) <- "rq"
                xsum[[i]] <- summary(xi, U = U, ...)
                if(i == 1 && length(xsum[[i]]$U)) U <- xsum[[i]]$U 
		if(class(object)[1] == "dynrqs"){
		    class(xsum[[1]]) <- c("summary.dynrq", "summary.rq")
	            if(i == 1) xsum[[1]]$model <- object$model
		    }
                }
        class(xsum) <- "summary.rqs"
	if(class(object)[1] == "dynrqs") 
	    class(xsum) <- c("summary.dynrqs", "summary.rqs")
        xsum
        }
"logLik.rq" <- function(object,  ...){
        n <- length(object$residuals)
        p <- length(object$coefficients)
	pen <- (length(object$lambda) > 0)
	tau <- object$tau
        fid <- object$rho
        val <- n * (log(tau * (1-tau)) - 1 - log(fid/n))
        attr(val,"n") <- n
	if(pen){
	   if(!hasArg(edfThresh)) edfThresh <- 0.0001
           attr(val,"df") <- sum(abs(object$coefficients) > edfThresh)
	  }
	else  attr(val,"df") <- p
        class(val) <- "logLik"
        val
        }
"logLik.rqs" <- function(object, ...){
        n <- nrow(object$residuals)
        p <- nrow(object$coefficients)
	pen <- (length(object$lambda) > 0)
	tau <- object$tau
        fid <- object$rho
        val <- n * (log(tau * (1-tau)) - 1 - log(fid/n))
        attr(val,"n") <- n
	if(pen){
	   if(!hasArg(edfThresh)) edfThresh <- 0.0001
           attr(val,"df") <- sum(abs(object$coefficients) > edfThresh)
	  }
	else  attr(val,"df") <- p
        class(val) <- "logLik"
        val
        }
"AIC.rq" <- function(object, ... , k = 2){
        v <- logLik(object)
        if(k <= 0)
                k <- log(attr(v,"n"))
        val <- AIC(v, k = k)
        attr(val,"edf") <- attr(v,"df")
        val
        }
"extractAIC.rq"  <- function(fit, scale, k=2, ...){
aic <- AIC(fit,k)
edf <- attr(aic, "edf")
c(edf, aic)
}

"AIC.rqs" <- function(object, ... , k = 2){
        v <- logLik(object)
        if(k <= 0)
                k <- log(attr(v,"n"))
        val <- AIC(v, k = k)
        attr(val,"edf") <- attr(v,"df")
        val
        }


"summary.rq" <-
# This function provides  methods for summarizing the output of the
# rq command. In this instance, "summarizing" means essentially provision
# of either standard errors, or confidence intervals for the rq coefficents.
# Since the preferred method for confidence intervals is currently the
# rank inversion method available directly from rq() by setting ci=TRUE, with br=TRUE.
# these summary methods are intended primarily for comparison purposes
# and for use on large problems where the parametric programming methods
# of rank inversion are prohibitively memory/time consuming.  Eventually
# iterative versions of rank inversion should be developed that would
# employ the Frisch-Newton approach.
#
# Object is the result of a call to rq(), and the function returns a
# table of coefficients, standard errors, "t-statistics", and p-values, and, if
# covariance=TRUE a structure describing the covariance matrix of the coefficients,
# i.e. the components of the Huber sandwich.
#
# There are five options for "se":
#
#	1.  "rank" strictly speaking this doesn't produce a "standard error"
#		at all instead it produces a coefficient table with confidence
#		intervals for the coefficients based on inversion of the
#		rank test described in GJKP and Koenker (1994).
#	2.  "iid" which presumes that the errors are iid and computes
#		an estimate of the asymptotic covariance matrix as in KB(1978).
#	3.  "nid" which presumes local (in tau) linearity (in x) of the
#		the conditional quantile functions and computes a Huber
#		sandwich estimate using a local estimate of the sparsity.
#	4.  "ker" which uses a kernel estimate of the sandwich as proposed
#		by Powell.
#	5.  "boot" which uses one of several flavors of  bootstrap methods:
#		"xy"	uses xy-pair method
#		"wxy"	uses weighted (generalized) method
#		"pwy"	uses the parzen-wei-ying method
#		"mcmb"	uses the Markov chain marginal bootstrap method
#		"cluster"  uses the Hagemann clustered wild gradient method
#		"BLB"	uses the Bag of Little Boostraps method
#
#
function (object, se = NULL, covariance = FALSE, hs = TRUE, U = NULL, gamma = 0.7, ...)
{
    if(object$method == "lasso")
         stop("no inference for lasso'd rq fitting: try rqss (if brave, or credulous)")
    mt <- terms(object)
    m <- model.frame(object)
    y <- model.response(m)
    dots <- list(...)
    if(object$method == "sfn")
	x <- object$model$x
    else
	x <- model.matrix(mt, m, contrasts = object$contrasts)
    wt <- as.vector(model.weights(object$model))
    tau <- object$tau
    eps <- .Machine$double.eps^(1/2)
    coef <- coefficients(object)
    if (is.matrix(coef))
        coef <- coef[, 1]
    vnames <- dimnames(x)[[2]]
    resid <- object$residuals
    n <- length(resid)
    p <- length(coef)
    rdf <- n - p
    if (!is.null(wt)) {
        resid <- resid * wt
        x <- x * wt
        y <- y * wt
    }
    if (is.null(se)) {
        if (n < 1001 & covariance == FALSE)
            se <- "rank"
        else se <- "nid"
    }
    if (se == "rank") {
        f <- rq.fit.br(x, y, tau = tau, ci = TRUE, ...)
    }
    if (se == "iid") {
        xxinv <- diag(p)
        xxinv <- backsolve(qr(x)$qr[1:p, 1:p,drop=FALSE], xxinv)
        xxinv <- xxinv %*% t(xxinv)
        pz <- sum(abs(resid) < eps)
        h <- max(p + 1, ceiling(n * bandwidth.rq(tau, n, hs = hs)))
        ir <- (pz + 1):(h + pz + 1)
        ord.resid <- sort(resid[order(abs(resid))][ir])
        xt <- ir/(n - p)
        sparsity <- rq(ord.resid ~ xt)$coef[2]
        cov <- sparsity^2 * xxinv * tau * (1 - tau)
        scale <- 1/sparsity
        serr <- sqrt(diag(cov))
    }
    else if (se == "nid") {
        h <- bandwidth.rq(tau, n, hs = hs)
	while((tau - h < 0) || (tau + h > 1)) h <- h/2
        bhi <- rq.fit.fnb(x, y, tau = tau + h)$coef
        blo <- rq.fit.fnb(x, y, tau = tau - h)$coef
        dyhat <- x %*% (bhi - blo)
        if (any(dyhat <= 0))
            warning(paste(sum(dyhat <= 0), "non-positive fis"))
        f <- pmax(0, (2 * h)/(dyhat - eps))
        fxxinv <- diag(p)
        fxxinv <- backsolve(qr(sqrt(f) * x)$qr[1:p, 1:p,drop=FALSE], fxxinv)
        fxxinv <- fxxinv %*% t(fxxinv)
        cov <- tau * (1 - tau) * fxxinv %*% crossprod(x) %*%
            fxxinv
        scale <- mean(f)
        serr <- sqrt(diag(cov))
    }
    else if (se == "ker") {
        h <- bandwidth.rq(tau, n, hs = hs)
	while((tau - h < 0) || (tau + h > 1)) h <- h/2
        uhat <- c(y - x %*% coef)
        h <- (qnorm(tau + h) - qnorm(tau - h))*
		min(sqrt(var(uhat)), ( quantile(uhat,.75)- quantile(uhat, .25))/1.34 )
        f <- dnorm(uhat/h)/h
        fxxinv <- diag(p)
        fxxinv <- backsolve(qr(sqrt(f) * x)$qr[1:p, 1:p,drop=FALSE], fxxinv)
        fxxinv <- fxxinv %*% t(fxxinv)
        cov <- tau * (1 - tau) * fxxinv %*% crossprod(x) %*%
            fxxinv
        scale <- mean(f)
        serr <- sqrt(diag(cov))
    }
    else if (se == "boot") {
	if("cluster" %in% names(dots)) {
	    bargs <- modifyList(list(x = x, y = y, tau = tau), dots)
	    if(length(object$na.action)) {
	         cluster <- dots$cluster[-object$na.action]
	         bargs <- modifyList(bargs, list(cluster = cluster))
	    }
	B <- do.call(boot.rq, bargs)
	}
	else
	    B <- boot.rq(x, y, tau, ...)
        cov <- cov(B$B)
        serr <- sqrt(diag(cov))
    }
   else if (se == "BLB"){ # Bag of Little Bootstraps
        n <- length(y)
        b <- ceiling(n^gamma)
        S <- n %/% b
        V <- matrix(sample(1:n, b * S), b, S)
        Z <- matrix(0, NCOL(x), S)
        for(i in 1:S){
            v <- V[,i]
	    B <- boot.rq(x[v,], y[v], tau, bsmethod = "BLB", blbn = n, ...)
            Z[,i] <- sqrt(diag(cov(B$B)))
        }
	cov <- cov(B$B)
        serr <- apply(Z, 1, mean)
    }
    if( se == "rank"){
	coef <- f$coef
	}
    else {
    	coef <- array(coef, c(p, 4))
    	dimnames(coef) <- list(vnames, c("Value", "Std. Error", "t value",
             "Pr(>|t|)"))
    	coef[, 2] <- serr
    	coef[, 3] <- coef[, 1]/coef[, 2]
    	coef[, 4] <- if (rdf > 0)
			2 * (1 - pt(abs(coef[, 3]), rdf))
    		     else NA
	}
    object <- object[c("call", "terms")]
    if (covariance == TRUE) {
        if(se != "rank") object$cov <- cov
        if(se == "iid") object$scale <- scale
        if(se %in% c("nid", "ker")) {
            object$Hinv <- fxxinv
            object$J <- crossprod(x)
            object$scale <- scale
        }
        else if (se == "boot") {
            object$B <- B$B
	    object$U <- B$U
        }
    }
    object$coefficients <- coef
    object$residuals <- resid
    object$rdf <- rdf
    object$tau <- tau
    class(object) <- "summary.rq"
    object
}

akj <- function(x,
                z = seq(min(x), max(x), length = 2 * length(x)),
                p = rep(1/length(x), length(x)),
                h = -1, alpha = 0.5, kappa = 0.9, iker1 = 0)
{
    nx <- length(x)
    stopifnot(is.numeric(x),
              length(p) == nx,
	      any((iker1 <- as.integer(iker1)) == 0:1))
    nz <- length(z)
    if(is.unsorted(x))
	x <- sort(x)
    .Fortran("sakj",
	     as.double(x),
	     as.double(z),
	     as.double(p),
	     iker1,
	     dens  = double(nz),
	     psi   = double(nz),
	     score = double(nz),
	     as.integer(nx),
	     as.integer(nz),
	     h = as.double(h),
	     as.double(alpha),
	     as.double(kappa),
	     double(nx))[c("dens", "psi", "score", "h")]
}

"lm.fit.recursive" <-
function(X, y, int = TRUE)
{
	if(int)
		X <- cbind(1, X)
	p <- ncol(X)
	n <- nrow(X)
	D <- qr(X[1:p,  ])
	A <- qr.coef(D, diag(p))
	A[is.na(A)] <- 0
	A <- crossprod(t(A))
	Ax <- rep(0, p)
	b <- matrix(0, p, n)
	b[, p] <- qr.coef(D, y[1:p])
	b[is.na(b)] <- 0
	z <- .Fortran( "rls",
		as.integer(n),
		as.integer(p),
		as.double(t(X)),
		as.double(y),
		b = as.double(b),
		as.double(A),
		as.double(Ax))
	bhat <- matrix(z$b, p, n)
	return(bhat)
}

"rq.fit.hogg" <-
function (x, y, taus = c(.1,.3,.5), weights = c(.7,.2,.1),  
	R= NULL, r = NULL, beta = 0.99995, eps = 1e-06) 
{
    n <- length(y)
    n2 <- NROW(R)
    m <- length(taus)
    p <- ncol(x)+m
    if (n != nrow(x)) 
        stop("x and y don't match n")
    if (m != length(weights)) 
        stop("taus and weights differ in length")
    if (any(taus < eps) || any(taus > 1 - eps)) 
        stop("taus outside (0,1)")
    W <- diag(weights)
    if(m == 1) W <- weights
    x <- as.matrix(x)
    X <- cbind(kronecker(W,rep(1,n)),kronecker(weights,x))
    y <- kronecker(weights,y)
    rhs <- c(weights*(1 - taus)*n, sum(weights*(1-taus)) * apply(x, 2, sum))
    if(n2!=length(r))
	stop("R and r of incompatible dimension")
    if(!is.null(R))
	if(ncol(R)!=p)
	    stop("R and X of incompatible dimension")
    d <- rep(1, m*n)
    u <- rep(1, m*n)
    if(length(r)){
       wn1 <- rep(0, 10 * m*n)
       wn1[1:(m*n)] <- .5
       wn2 <- rep(0,6*n2)
       wn2[1:n2] <- 1 
       z <- .Fortran("rqfnc", as.integer(m*n), as.integer(n2), as.integer(p), 
           a1 = as.double(t(as.matrix(X))), c1 = as.double(-y), 
           a2 = as.double(t(as.matrix(R))), c2 = as.double(-r), 
           rhs = as.double(rhs), d1 = double(m*n), d2 = double(n2), 
           as.double(u), beta = as.double(beta), eps = as.double(eps), 
           wn1 = as.double(wn1), wn2 = as.double(wn2), wp = double((p + 3) * p), 
	   it.count = integer(3), info = integer(1))
	}
    else{
	wn <- rep(0, 10 * m*n)
    	wn[1:(m*n)] <- .5
    	z <- .Fortran("rqfnb", as.integer(m*n), as.integer(p), a = as.double(t(as.matrix(X))), 
		c = as.double(-y), rhs = as.double(rhs), d = as.double(d), as.double(u), 
		beta = as.double(beta), eps = as.double(eps), wn = as.double(wn), 
		wp = double((p + 3) * p), it.count = integer(2), info = integer(1))
	}
    if (z$info != 0) 
        warning(paste("Info = ", z$info, "in stepy: singular design: iterations ", z$it.count[1]))
    coefficients <- -z$wp[1:p]
    if(any(is.na(coefficients)))stop("NA coefs:  infeasible problem?")
    list(coefficients = coefficients, nit = z$it.count, flag = z$info)
}
